﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PubSubLite.Configuration;

namespace PubSubLite
{
    /// <summary>
    /// This is the public interface of PubSubLite, represening a message bus.
    /// </summary>
    public interface IBus
    {
        /// <summary>
        /// Configure the bus using a fluent syntax. Configure() returns an IBusConfigurationSetup
        /// where every method returns the same instance.
        /// </summary>
        /// <returns></returns>
        IBusConfigurationSetup Configure(Func<IBusConfiguration, IBusConfigurationSetup> config);
        
        /// <summary>
        /// Configure the bus using a fluent syntax. Configure() returns an IBusConfigurationSetup
        /// where every method returns the same instance.
        /// </summary>
        /// <returns></returns>
        IBusConfigurationSetup Configure();

        /// <summary>
        /// Subscribes the supplied subscribers to the type of messages
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="subscriptions"></param>
        /// <returns></returns>
        IEnumerable<ISubscription<T>> SubscribeAll<T>(Func<IEnumerable<ISubscriber<T>>> subscriptions);

        /// <summary>
        /// Subscribes to all messages is of the supplied type
        /// </summary>
        /// <typeparam name="T">The type of the data of the message</typeparam>
        /// <param name="subscriber">The subscriber</param>
        /// <returns>A <see cref="Subscription{T}"></see></returns>
        ISubscription<T> Subscribe<T>(ISubscriber<T> subscriber);

        /// <summary>
        /// Unsubscribes to the subscription with a corresponding ID
        /// </summary>
        /// <param name="subscriptionID"></param>
        void Unsubscribe(Guid subscriptionID);

        /// <summary>
        /// Publishes a message on the bus
        /// </summary>
        /// <typeparam name="T">type of the data</typeparam>
        /// <param name="data">Data of the message</param>
        void Publish<T>(T data) where T : class;

        /// <summary>
        /// Publishes a message on the bus
        /// </summary>
        /// <typeparam name="T">type of the data</typeparam>
        /// <param name="data">Data of the message</param>
        /// <param name="category">Message category, could be any string to identify the category</param>
        void Publish<T>(T data, string category) where T : class;

        /// <summary>
        /// Publishes a command on the bus. A command can have one and only one receiver.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TReturnMessageType"></typeparam>
        /// <param name="data"></param>
        /// <param name="callback"></param>
        void PublishCommand<T, TReturnMessageType>(T data, Action<TReturnMessageType> callback) where T : class;

        /// <summary>
        /// Publishes a reply to the initializer of a command.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        /// <param name="correlatingMessageID">Id of the received command</param>
        void PublishCommandReply<T>(T data, Guid correlatingMessageID) where T : class;

        /// <summary>
        /// Removes all the subscribers
        /// </summary>
        void ClearSubscribers();

    }
}
